<!DOCTYPE html>
<html>
<head>
    <title>Physics Diagram: Spring-Mass System</title>
</head>
<body>
<canvas id="physicsCanvas" width="700" height="550" style="border:1px solid #d3d3d3;"></canvas>

<script>
    const canvas = document.getElementById('physicsCanvas');
    const ctx = canvas.getContext('2d');

    // --- Helper Functions ---

    /**
     * Draws an arrow from one point to another.
     * @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
     * @param {number} fromx - The starting x-coordinate.
     * @param {number} fromy - The starting y-coordinate.
     * @param {number} tox - The ending x-coordinate.
     * @param {number} toy - The ending y-coordinate.
     */
    function drawArrow(ctx, fromx, fromy, tox, toy) {
        const headlen = 10;
        const dx = tox - fromx;
        const dy = toy - fromy;
        const angle = Math.atan2(dy, dx);
        ctx.beginPath();
        ctx.moveTo(fromx, fromy);
        ctx.lineTo(tox, toy);
        ctx.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
        ctx.moveTo(tox, toy);
        ctx.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
        ctx.stroke();
    }
    
    /**
     * Draws a spring with loops on one side, as depicted in the diagram.
     * @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
     * @param {number} startX - The starting x-coordinate of the spring.
     * @param {number} startY - The y-coordinate (centerline).
     * @param {number} endX - The ending x-coordinate.
     * @param {number} endY - The ending y-coordinate.
     * @param {number} numLoops - The number of coils.
     */
    function drawStyledSpring(ctx, startX, startY, endX, endY, numLoops) {
        ctx.beginPath();
        const length = endX - startX;
        const hookHeight = 10;
        const loopSectionLength = length;
        const loopRadius = loopSectionLength / (numLoops * 2);

        // Wall hook (attachment point)
        ctx.moveTo(startX, startY - hookHeight);
        ctx.lineTo(startX, startY + hookHeight);
        
        // Loops
        let currentX = startX;
        for (let i = 0; i < numLoops; i++) {
            ctx.arc(currentX + loopRadius, startY, loopRadius, Math.PI, 0, false);
            currentX += 2 * loopRadius;
        }

        // Connecting to block hook
        ctx.lineTo(endX, startY);
        // Block hook (attachment point)
        ctx.moveTo(endX, startY - hookHeight);
        ctx.lineTo(endX, startY + hookHeight);
        
        ctx.stroke();
    }

    // --- Main Drawing Logic ---

    // Style setup
    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'black';
    ctx.lineWidth = 2;

    // Define coordinates and dimensions
    const floorY = 400;
    const wallX = 120;
    const blockWidth = 120;
    const blockHeight = 80;
    const springLength = 250;
    const blockX = wallX + springLength;
    const blockY = floorY - blockHeight;
    const springY = floorY - blockHeight / 2;

    // 1. Draw Floor and Wall
    ctx.beginPath();
    ctx.moveTo(wallX - 50, floorY);
    ctx.lineTo(canvas.width - 50, floorY); // Floor
    ctx.moveTo(wallX, floorY + 20);
    ctx.lineTo(wallX, floorY - 200);      // Wall
    ctx.stroke();

    // 2. Draw Hatching for fixed surfaces
    ctx.lineWidth = 1;
    // Floor hatching
    for (let i = wallX - 40; i < canvas.width - 50; i += 20) {
        ctx.beginPath();
        ctx.moveTo(i, floorY);
        ctx.lineTo(i - 15, floorY + 15);
        ctx.stroke();
    }
    // Wall hatching
    for (let i = floorY - 190; i < floorY + 20; i += 20) {
        ctx.beginPath();
        ctx.moveTo(wallX, i);
        ctx.lineTo(wallX - 15, i - 15);
        ctx.stroke();
    }
    ctx.lineWidth = 2;

    // 3. Draw Spring
    drawStyledSpring(ctx, wallX, springY, blockX, springY, 6);

    // 4. Draw Block m'
    ctx.beginPath();
    ctx.rect(blockX, blockY, blockWidth, blockHeight);
    ctx.stroke();
    ctx.font = 'italic 28px "Times New Roman"';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText("m'", blockX + blockWidth / 2, blockY + blockHeight / 2);

    // 5. Draw Particle m
    const particleRadius = 7;
    const particleX = blockX + blockWidth / 2;
    const fallHeight = 150;
    const particleY = blockY - fallHeight;
    ctx.beginPath();
    ctx.arc(particleX, particleY, particleRadius, 0, 2 * Math.PI);
    ctx.fill();
    ctx.fillText("m", particleX - 30, particleY);

    // 6. Draw Falling Arrow
    drawArrow(ctx, particleX, particleY + 15, particleX, particleY + 70);

    // 7. Draw Height 'h'
    const h_line_x = blockX + blockWidth + 80;
    ctx.beginPath();
    ctx.moveTo(h_line_x, particleY);
    ctx.lineTo(h_line_x, blockY); // Vertical line
    ctx.moveTo(h_line_x - 10, particleY);
    ctx.lineTo(h_line_x + 10, particleY); // Top tick
    ctx.moveTo(h_line_x - 10, blockY);
    ctx.lineTo(h_line_x + 10, blockY); // Bottom tick
    ctx.stroke();
    ctx.fillText("h", h_line_x + 25, (particleY + blockY) / 2);

    // 8. Draw Caption
    ctx.font = '28px "SimSun", "Songti SC"';
    ctx.fillText("习题 10-8 图", canvas.width / 2, floorY + 60);

</script>
</body>
</html>